#include <stdio.h>
#include <argp.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include "missive/crypt.h"

typedef struct {
	const char *secret;
        const char *public;
} Args;

const char *argp_program_version = "box_keys 1.0";
const char *argp_program_bug_address = "<todo: add email>";

static char doc[] = "box_keys -- a generates box keys";

static char args_doc[] = "SECRET PUBLIC";

static error_t
parse_opt(int key, char *arg, struct argp_state *state)
{
	/* Get the input argument from argp_parse, which we
	   know is a pointer to our arguments structure. */
	Args *args = state->input;

	switch (key) {
	case ARGP_KEY_NO_ARGS:
		break;
	case ARGP_KEY_ARG:
		if (!state->arg_num)
			args->secret = arg;
		else if (state->arg_num == 1)
			args->public = arg;
		else
			argp_usage(state);

		break;
	case ARGP_KEY_END:
		if (state->arg_num < 2)
			argp_usage(state);

		break;
	default:
		return ARGP_ERR_UNKNOWN;
	}

	return 0;
}

static struct argp argp = { NULL, parse_opt, args_doc, doc };

void
deal_with_args(int argc, char *argv[])
{
	Box_skey skey;
	Box_pkey pkey;
	int sfd;
	int pfd;
	ssize_t size;
	Args args;

	argp_parse(&argp, argc, argv, 0, 0, &args);

	if ((sfd = open(args.secret,
			O_CREAT | O_WRONLY, S_IWUSR | S_IRUSR)) < 0) {
		perror("Failed to open secret key file");
		exit(EXIT_FAILURE);
	}

	if ((pfd = open(args.public, O_CREAT | O_WRONLY,
			S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH)) < 0) {
		perror("Failed to open public key file");
		exit(EXIT_FAILURE);
	}

	box_keys(skey, pkey);

	if ((size = write(sfd, skey, sizeof(skey))) <
	    (ssize_t) sizeof(skey)) {
		if (size < 0)
			perror("Failed to write secret key file");
		else
			fprintf(stderr, "Secret key write interrupted");

		exit(EXIT_FAILURE);
	}

	if (fsync(sfd) < 0) {
		perror("Failed to write secret key file");
		exit(EXIT_FAILURE);
	}

	if ((size = write(pfd, pkey, sizeof(pkey))) <
	    (ssize_t) sizeof(pkey)) {
		if (size < 0)
			perror("Failed to write public key file");
		else
			fprintf(stderr, "Public key write interrupted");

		exit(EXIT_FAILURE);
	}

	if (fsync(sfd) < 0) {
		perror("Failed to write public key file");
		exit(EXIT_FAILURE);
	}

	close(sfd);
	close(pfd);
}

int
main(int argc, char *argv[])
{
	deal_with_args(argc, argv);
	return 0;
}
